package com.haiya.identityaccess.infrastructure.persistence.mybatis.repository;

import com.haiya.identityaccess.domain.identity.model.*;
import com.haiya.identityaccess.domain.identity.repository.UserRepository;
import com.haiya.identityaccess.infrastructure.persistence.mybatis.datamodel.DataPerson;
import com.haiya.identityaccess.infrastructure.persistence.mybatis.datamodel.DataUser;
import com.haiya.identityaccess.infrastructure.persistence.mybatis.mapper.PersonMapper;
import com.haiya.identityaccess.infrastructure.persistence.mybatis.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author qiaoguoqiang
 */
@Repository
public class UserRepositoryImpl implements UserRepository {
    @Autowired
    UserMapper userMapper;

    @Autowired
    PersonMapper personMapper;

    /**
     * 添加用户
     * 1. 添加用户表
     * 2. 添加用户联系信息表 (这里的主键是上面用户表的主键)
     * @param aUser
     */
    @Override
    public void add(User aUser) {
        TenantId tenantId = aUser.tenantId();
        Enablement enablement = aUser.enablement();
        Person person = aUser.person();
        DataUser dataUser = new DataUser(
                tenantId.id(),
                aUser.username(),
                aUser.password(),
                enablement.isEnablementEnabled() ? 1 : 0,
                enablement.startDate(),
                enablement.endDate());
        int userId = userMapper.insert(dataUser);

        DataPerson dataPerson = new DataPerson(
                dataUser.getId(),
                tenantId.id(),
                person.name().firstName(),
                person.name().lastName(),
                person.contactInformation().emailAddress().address(),
                person.contactInformation().postalAddress().city(),
                person.contactInformation().postalAddress().countryCode(),
                person.contactInformation().postalAddress().postalCode(),
                person.contactInformation().postalAddress().stateProvince(),
                person.contactInformation().postalAddress().streetAddress(),
                person.contactInformation().primaryTelephone().number(),
                person.contactInformation().secondaryTelephone().number());
        personMapper.addPerson(dataPerson);
    }

    @Override
    public Collection<User> allSimilarlyNamedUsers(TenantId aTenantId, String aFirstNamePrefix, String aLastNamePrefix) {
        List<DataUser> dataUsers = userMapper.allSimilarlyNamedUsers(aTenantId.id(), aFirstNamePrefix, aLastNamePrefix);

        Collection<User> users = new ArrayList<>();
        /**
         * 这里先不考虑效率问题
         */
        for (DataUser dataUser : dataUsers) {
            DataPerson dataPerson = personMapper.selectById(dataUser.getId());
            users.add(createUserFromDataEntity(aTenantId, dataUser, dataPerson));
        }

        return users;
    }

    @Override
    public void remove(User aUser) {
        DataUser dataUser = userMapper.userWithUsername(aUser.tenantId().id(), aUser.username());
        if (dataUser != null) {
            userMapper.deleteById(dataUser.getId());
            personMapper.deleteById(dataUser.getId());
        }
    }

    @Override
    public User userFromAuthenticCredentials(TenantId aTenantId, String aUsername, String anEncryptedPassword) {
        DataUser dataUser = userMapper.userFromAuthenticCredentials(aTenantId.id(), aUsername, anEncryptedPassword);
        DataPerson dataPerson = personMapper.selectById(dataUser.getId());
        return createUserFromDataEntity(aTenantId, dataUser, dataPerson);
    }

    /**
     * 使用租户及用户名查找用户实体 暂时先临时实现一下，后续看如何重构
     * @param aTenantId
     * @param aUsername
     * @return
     */
    @Override
    public User userWithUsername(TenantId aTenantId, String aUsername) {
        DataUser dataUser = userMapper.userWithUsername(aTenantId.id(), aUsername);
        DataPerson dataPerson = personMapper.selectById(dataUser.getId());
        return createUserFromDataEntity(aTenantId, dataUser, dataPerson);
    }

    /**
     * 简单封装一个从数据库实体到领域实体User的方法
     * @param aTenantId
     * @param dataUser
     * @param dataPerson
     * @return
     */
    private User createUserFromDataEntity(TenantId aTenantId, DataUser dataUser, DataPerson dataPerson) {
        Enablement enablement = new Enablement(
                dataUser.getEnablementEnabled() == 1,
                dataUser.getEnablementStartDate(),
                dataUser.getEnablementEndDate());
        FullName fullName = new FullName(dataPerson.getNameFirstName(), dataPerson.getNameLastName());
        EmailAddress emailAddress = new EmailAddress(dataPerson.getContactInformationEmailAddressAddress());
        PostalAddress postalAddress = new PostalAddress(
                dataPerson.getContactInformationPostalAddressStreetAddress(),
                dataPerson.getContactInformationPostalAddressCity(),
                dataPerson.getContactInformationPostalAddressStateProvince(),
                dataPerson.getContactInformationPostalAddressPostalCode(),
                dataPerson.getContactInformationPostalAddressCountryCode());
        Telephone primaryTelphone = new Telephone(dataPerson.getContactInformationPrimaryTelephoneNumber());
        Telephone secondaryTelphone = new Telephone(dataPerson.getContactInformationSecondaryTelephoneNumber());

        ContactInformation contactInformation =
                new ContactInformation(emailAddress, postalAddress, primaryTelphone, secondaryTelphone);
        Person person = new Person(
                aTenantId,
                fullName,
                contactInformation);
        return new User(aTenantId, dataUser.getUsername(), enablement, person);
    }
}
